#include "playmp3.h"

#include "mad.h"
#include "file.h"
#include "LoopBytes.h"

#include "typedef.h"
#include "audio_pub.h"
#include "LoopRec.h"


#define debug printf
#define assert(x) if (!(x)) {printf("assert error: %s!\r\n", __FUNCTION__); while (1) {};}

static struct StLoopBytesMgr *pWavLoopMgr = 0;


int decode_wav();

typedef struct StWavStream {
    int nReaded;
    int nPos;
    int wav_samplerate;
    int channel;
    int (*getdata)(unsigned char *buf, int len, int timeout);
}StWavStream;

static struct StWavStream gWavStream;


int WavPlayData(unsigned char *buf, int len, unsigned int timeout)
{
    struct StWavStream *pMgr = &gWavStream;
    int ret = 0;
    if (len<=0) return -1;
    if (pWavLoopMgr) {
        ret = LoopBytesMgrPushPend(pWavLoopMgr, buf, len, timeout, 0);
    }
    return ret;
}

int wav_loopbytes_len()
{
    if (pWavLoopMgr)
    {
        return LoopBytesMgrTotals(pWavLoopMgr);
    }
    return 0;
}

int wav_loopbytes_is_empty()
{
    if (pWavLoopMgr) {
        return LoopBytesMgrTotals(pWavLoopMgr)==0;
    }
    return 0;
}



void clear_wav_stream() {
    struct StWavStream *pMgr = &gWavStream;
}

void UserSetAudioOpt(int channel, int samplerate)
{
    struct StWavStream *priv= &gWavStream;
    priv->channel = channel;
    priv->wav_samplerate = samplerate;
}

void SetAudioOpt()
{
    struct StWavStream *priv= &gWavStream;
    static int local_samplerate=0;
    static int local_volume=0;
    static int local_channel = 1;

    if (local_channel != priv->channel) {
          local_channel = priv;
          djy_audio_dac_close();
          djy_audio_dac_open(AUDIO_DMA_BUFF_SIZE, local_channel, priv->wav_samplerate);
          //djy_audio_dac_ctrl(AUD_DAC_CMD_SET_VOLUME,&local_volume);
      }

    if (local_samplerate != priv->wav_samplerate) {
        local_samplerate = priv->wav_samplerate;
        switch (priv->wav_samplerate) {
            case    audio_sample_rate_11025:
            case    audio_sample_rate_22050:
            case    audio_sample_rate_44100:
            case    audio_sample_rate_12000:
            case    audio_sample_rate_24000:
            case    audio_sample_rate_48000:
            case    audio_sample_rate_8000:
            case    audio_sample_rate_16000:
            case    audio_sample_rate_32000:
                local_samplerate = priv->wav_samplerate;
                break;
            default:
                local_samplerate = audio_sample_rate_44100;
                break;
        }
        djy_audio_dac_ctrl(AUD_DAC_CMD_SET_SAMPLE_RATE,&local_samplerate);
        debug("==== info: audio_opt, set sample rate: %d! ====\r\n", local_samplerate);
    }
}


extern uint32_t media_data_send(char *buf, uint32_t len);
int decode_wav()
{

    int ret = 0;
    int n = 0;
    int length = 2*1024;
    unsigned char *pbuf = malloc(length);
    if (pbuf == 0) {
        printf("error: decode_wav, malloc failed!\r\n");
        return 0;
    }

    while (pWavLoopMgr) {
        ret = LoopBytesMgrPullPend(pWavLoopMgr, pbuf,  length, 0xFFFFFFFF, 0);
        SetAudioOpt();
        int writed = 0;
        while (1) {
             ret = media_data_send(pbuf+writed, length-writed);
             //ret = djy_audio_dac_write(pbuf+writed, length-writed);
             if (ret > 0) {
                 writed += ret;
             }
             if (writed < length) {
                 Djy_EventDelay(10*1000);
             }
             else {
                 break;
             }
         }
    }

    free(pbuf);
    return ret;
}

int wav_play_from_file(char *path)
{
    int ret = 0;
    int length = 1024;
    FILE *f = fopen(path, "rb");
    if (f == 0) {
        printf("error: wav_play_from_file, path=%s!\r\n", path);
        return -1;
    }
    fseek(f, 0L, SEEK_END);
    int file_size = ftell(f);
    fseek(f, 0L, SEEK_SET);
    printf ("info: file size: %d!\r\n", file_size);

    unsigned char *p = (unsigned char*)malloc(length);
    if (p == 0) goto ERROR_RET;

    int n = 0;
    int pos = 0;
    int offset = 0;
    while (1) {
        if (offset >= file_size) break;
        n = fread(p, 1, length, f);
        if (n > 0) {
            offset += n;
            pos = 0;
            while (1) {
                if (pos >= n) break;
                ret = WavPlayData(p+pos, n-pos, 5000);
                if (ret > 0){
                    pos += ret;
                }
                else {
                    printf("wav_play_from_file->WavPlayData, ret=%d!\r\n", ret);
                    Djy_EventDelay(300*1000);
                }
            }
        }
        else {
            printf("wav_play_from_file->fread, n=%d!\r\n", n);
            Djy_EventDelay(300*1000);
        }
    }

ERROR_RET:
    if (f) fclose(f);
    if (p) free(p);
    return 0;
}

int wav_stream_reset()
{
    if (pWavLoopMgr) {
        LoopBytesMgrReset(pWavLoopMgr);
    }
    return 0;
}

int media_init();

int wav_module_init()
{
    struct StWavStream *pMgr = &gWavStream;
    memset(pMgr, 0, sizeof(struct StWavStream));
    pMgr->channel = 1;

    media_init();

    int ret = 0;
    djy_audio_dac_open(AUDIO_DMA_BUFF_SIZE, 1, audio_sample_rate_16000);

    int volume = 80;
    djy_audio_dac_ctrl(AUD_DAC_CMD_SET_VOLUME, &volume);

    pWavLoopMgr = LoopBytesMgrInit(500*1024, 256, 500*1024);
    if (pWavLoopMgr == 0) {
        printf("error: %s->LoopBytesMgrInit failed!\r\n", __FUNCTION__);
        return -1;
    }

    u16 task_playwav = Djy_EvttRegist(EN_CORRELATIVE, CN_PRIO_REAL-2, 0, 1, decode_wav, NULL, 0x4000,"playwav");
    if(task_playwav != CN_EVTT_ID_INVALID)
    {
        Djy_EventPop(task_playwav,NULL,0,NULL,0,0);
    }
}


